﻿using Core.DataAccess.ApiJson.SearchService;
using Core.Framework;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Core.DataAccess.ApiJson.Controllers
{
    public class DatabaseSchemaController : BaseSchema
    {
        public DatabaseSchemaController(SqlSugarClient sqlSugarClient, ISearchProvider searchProvider) : base(sqlSugarClient, searchProvider)
        {
            base.sqlSugarClient.DbMaintenance.CreateDatabase();
        }

        /// <summary>
        /// 还原数据库
        /// </summary>
        /// <param name="schemaString"></param>
        public void RestoreDataBase(string dbtitle, string schemaString, Action<Dictionary<string, TableSchema>> callback)
        {
            if (string.IsNullOrWhiteSpace(schemaString))
                throw new Exception("input schemaString is null");

            // 获取上一份配置文件
            string filePath = $"./{dbtitle}-tableSchema-new.json";
            Dictionary<string, TableSchema> oldSchema = new Dictionary<string, TableSchema>();
            if (File.Exists(filePath))
            {
                oldSchema = JsonConvert.DeserializeObject<Dictionary<string, TableSchema>>(File.ReadAllText(filePath));
            }

            // 系列化schema信息
            var schema = JsonConvert.DeserializeObject<Dictionary<string, TableSchema>>(schemaString);
            if (schema == null)
                throw new Exception("schema is null");

            // 初始化数据结构和数据
            this.DataBaseStructuralSynchronization(schema);

            // 初始化索引
            this.IniSearchIndex(schema, oldSchema);

            // 写入本次文件
            File.WriteAllText(filePath, JsonConvert.SerializeObject(schema));

            callback.Invoke(schema);
        }

        /// <summary>
        /// 导出数据库到文件
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="fileName"></param>
        public void ExportDataBaseToFile(string filePath, string fileName, bool isExcludeTableData = false)
        {
            List<ExcludeRule> excludeRules = default;
            AppSetting.Bind("ExportDataBaseOfExcludeRules", excludeRules);
            excludeRules = excludeRules ?? new List<ExcludeRule>();

            Dictionary<string, TableSchema> keyValues = new Dictionary<string, TableSchema>();

            var tables = sqlSugarClient.DbMaintenance.GetTableInfoList(false);
            tables = tables.Where(t => !excludeRules.Any(e => e.IsIgnoreTable && e.TableName == t.Name)).ToList();

            foreach (var item in tables)
            {
                var tableSchema = new TableSchema();

                tableSchema.Columns = this.GetColumnsByTable(item.Name);

                var tableTitle = sqlSugarClient.Ado.GetString($"SELECT top 1 TABLE_SCHEMA from information_schema.columns WHERE TABLE_NAME = '{item.Name}'");

                // 检查是否排除表数据
                if (!isExcludeTableData)
                {
                    if (!excludeRules.Any(e => e.IsIgnoreData && e.TableName == item.Name))
                    {
                        var tableData = sqlSugarClient.Ado.GetDataTable($"select * from [{tableTitle}].[{item.Name}]");
                        var defaultData = JsonConvert.DeserializeObject<List<JObject>>(JsonConvert.SerializeObject(tableData));
                        tableSchema.DefaultData = defaultData;
                    }
                }

                keyValues.Add(item.Name, tableSchema);
            }

            // 文件完整路径
            string path = Path.Combine(filePath, fileName);

            DirectoryInfo info = new DirectoryInfo(path);

            // 文件夹是否存在
            if (!Directory.Exists(info.Parent.FullName))
                Directory.CreateDirectory(info.Parent.FullName);

            var jSetting = new JsonSerializerSettings
            {
                NullValueHandling = NullValueHandling.Ignore,
                DefaultValueHandling = DefaultValueHandling.Ignore
            };

            // 写入源文件
            File.WriteAllText(path, JsonConvert.SerializeObject(keyValues, jSetting));
        }

        public void IniDataBaseToFile(string dbtitle)
        {
            // 获取上一份配置文件
            string filePath = $"./{dbtitle}-tableSchema-new.json";
            if (!File.Exists(filePath))
            {
                this.ExportDataBaseToFile("./", $"{dbtitle}-tableSchema-new.json", true);
            }
        }
    }
}
